package com.chesnutconsulting.reports;

import java.io.FileInputStream;
import java.io.IOException;
import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import javax.servlet.ServletContext;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import net.sf.jasperreports.engine.JasperCompileManager;
import net.sf.jasperreports.engine.JasperFillManager;
import net.sf.jasperreports.engine.JasperPrint;
import net.sf.jasperreports.engine.JasperReport;
import net.sf.jasperreports.j2ee.servlets.BaseHttpServlet;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;

@Controller
public class JasperReportServlet extends HttpServlet {

	private static final long serialVersionUID = 1L;

	private Connection conn = null;
	private Log log = LogFactory.getLog(JasperReportServlet.class);

	public JasperReportServlet() {
		super();
	}

	public void destroy() {
		super.destroy();
	}

	@RequestMapping(value = "/get-report", method = RequestMethod.GET)
	public void getReport(HttpServletRequest request,
			HttpServletResponse response) throws ServletException, IOException {
		log.debug("DEBUGGING");
		/*
		 * These parameters do not need to be processed by the Jasper Engine
		 */
		List<String> excludeParams = new ArrayList<String>();
		excludeParams.add("REPORTNAME");
		excludeParams.add("OUTPUTTYPE");

		try {
			String reportName = request.getParameter("reportName");
			String outputType = request.getParameter("outputType");

			log.info("report name: " + reportName);
			log.info("output format: " + outputType);

			ServletContext context = request.getSession().getServletContext();
			JasperReport report = JasperCompileManager.compileReport(context
					.getRealPath("/WEB-INF/reports/" + reportName + ".jrxml"));

			conn = this.getConnection(context);

			Map<String, Object> parameters = this.setAllParameters(request,
					excludeParams);

			log.info("parameters being passed to jasper: "
					+ parameters.toString());

			JasperPrint jasperPrint = JasperFillManager.fillReport(report,
					parameters, conn);

			request.getSession().setAttribute(
					BaseHttpServlet.DEFAULT_JASPER_PRINT_SESSION_ATTRIBUTE,
					jasperPrint);

			if (outputType.equalsIgnoreCase("pdf"))
				context
						.getRequestDispatcher("/servlet/pdf")
						.forward(request, response);
			else if (outputType.equalsIgnoreCase("xls"))
				context
						.getRequestDispatcher("/servlet/xls")
						.forward(request, response);
			else if (outputType.equalsIgnoreCase("html"))
				context
						.getRequestDispatcher("/servlet/html")
						.forward(request, response);
		} catch (Exception e) {
			log.error(e.getMessage());
			log.error(ExceptionUtils.getFullStackTrace(e));
		}

	}

	private Map<String, Object> setAllParameters(HttpServletRequest request,
			List<String> excludeParams) {
		Map<String, Object> parameters = new HashMap<String, Object>();

		Enumeration<String> e = request.getParameterNames();

		while (e.hasMoreElements()) {
			String nextElem = e.nextElement();
			if (nextElem != null
					&& !excludeParams.contains(nextElem.toUpperCase())) {
				String val = StringUtils.defaultString(request
						.getParameter(nextElem));
				if (!val.equals("")) {
					parameters.put(nextElem, val);
				}
			}
		}

		return parameters;
	}

	private Connection getConnection(ServletContext context) {
		try {
			if (conn == null || (conn != null && conn.isClosed())) {
				/*
				 * String username = "qtsdamuser"; String password =
				 * "qtsdamuser"; String connUrl =
				 * "jdbc:sqlserver://localhost:1433;databaseName=QTSDAMDB";
				 */

				String propertiesFileLoc = context
						.getRealPath("/WEB-INF/reports.properties");

				Properties props = new Properties();
				props.load(new FileInputStream(propertiesFileLoc));

				String username = props.getProperty("username");
				String password = props.getProperty("password");
				String connUrl = props.getProperty("connectionString");

				try {

					Class.forName(props.getProperty("driver"));
					conn = java.sql.DriverManager.getConnection(connUrl,
							username, password);
					/*
					 * Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver"
					 * ); conn = java.sql.DriverManager.getConnection(connUrl,
					 * username, password);
					 */
				} catch (Exception e) {
					log.error(e.getMessage());
					log.error(ExceptionUtils.getFullStackTrace(e));
				}
			}
		} catch (SQLException e) {
			log.error(e.getMessage());
			log.error(ExceptionUtils.getFullStackTrace(e));
		} catch (IOException e) {
			log.error(e.getMessage());
			log.error(ExceptionUtils.getFullStackTrace(e));
		}
		return conn;
	}

	/**
	 * The doPost method of the servlet. <br>
	 * 
	 * This method is called when a form has its tag value method equals to
	 * post.
	 * 
	 * @param request
	 *            the request send by the client to the server
	 * @param response
	 *            the response send by the server to the client
	 * @throws ServletException
	 *             if an error occurred
	 * @throws IOException
	 *             if an error occurred
	 */
	public void doPost(HttpServletRequest request, HttpServletResponse response)
			throws ServletException, IOException {
		doGet(request, response);
	}

	/**
	 * Initialization of the servlet. <br>
	 * 
	 * @throws ServletException
	 *             if an error occure
	 */
	public void init() throws ServletException {
		// Put your code here
	}
}
